'''
Created on 2011-2-1
@author: wilbur.ma
'''
import os
import time
import shutil

from pwilib.util.FDUtil import FDUtil
from pwilib.util.plugin.PluginManagers import DefaultPluginManager

class SourceRepository(object):
    '''
    A simple source repository abstraction.
    
    * Backup
    * Project source code integration
    * Upload by FTP
    * Support plugin
    '''
    version_number = 0.1
    sr_pref = 'sr'
    sr_directories = {
                     'sr_dev'       : 'devp',
                     'sr_sta'       : 'stable',
                     'sr_cur'       : 'current',
                     'sr_log'       : 'log',
                     'sr_plugins'   : 'plugins',
                     }
    sr_files = {
                'sr_time'           : sr_pref + '.timestamp',
                'sr_ini'            : sr_pref + '.ini',
                }
    
    sr_plugins = {
                  'SrcCrawler'          : 'sr_crawler',
                  'Compressor'          : 'sr_compressor',
                  'FTP'                 : 'sr_ftp',
                  }
    
    def __init__(self, path = None):
        '''
        Constructor
        '''
        # Set path of the repository
        if path is None:
            self.path = os.curdir()
        else:    
            self.path = os.path.abspath(path)
        
        # self.create_dir_struct()
        # self.gen_config_file()
        # self.init_plugin_manager()
        
        
    def _create_dir_struct(self, force):
        '''
        Create the directory structure.
        '''
        if (not force) and os.path.exists(self.path):
            print(self.path, "already exists.")
            return
        # os.mkdir(self.path)
        for k in self.sr_directories.keys():
            os.mkdir(os.path.join(self.path, self.sr_directories[k]))
    
    
    def _init_plugin_manager(self):
        '''
        Initialize the plugin manager.
        '''
        configFile = os.path.join(self.path, self.sr_files['sr_ini'])
        pluginDir = os.path.join(self.path, self.sr_directories['sr_plugins'])
        self.manager = DefaultPluginManager(config_file = configFile, plugin_dir = pluginDir)
        # Register plugins
        for k in self.sr_plugins.keys():
            self.manager.register(self.sr_plugins[k])
        
        
    def _gen_config_file(self, ini_content = None):
        '''
        Generate the default configuration file.
        '''
        if ini_content is None:
            ini_content = '[backup]\n[plugins]'
        ini_path = os.path.join(self.path, self.sr_files['sr_ini'])
        if os.path.exists(ini_path):
            print(ini_path, 'already exists.')
            return
        with open(ini_path, 'w', encoding="utf-8") as ini_f:
            ini_f.write(ini_content)
        
        
    def _copy_to_current(self, workspaces):
        crawler = self.manager.get_plugin(self.sr_plugins['SrcCrawler'])
        target = os.path.join(self.path, self.sr_directories['sr_cur'])
        for src in crawler.getLocations(workspaces):
            FDUtil.copytree(src, target)
        # make timestamp
        self.make_timestamp(os.path.join(target, self.sr_files['sr_time']))
        
        
    def _make_timestamp(self, timefile):
        time_str = 'Last modified on: ' + time.asctime()
        with open(timefile, 'w') as time_f:
            time_f.write(time_str)
        
        
    def _compress_src(self, stable):
        compressor = self.manager.get_plugin(self.sr_plugins['Compressor'])
        src = os.path.join(self.path, self.sr_directories['sr_cur'])
        to_dir = self.sr_directories['sr_sta']
        if not stable:
            to_dir = self.sr_directories['sr_dev']
        target = os.path.join(self.path, 
                              to_dir,
                              time.strftime('%Y%m%d%H%M%S', time.localtime()) + '-sr_backup.zip')
        compressor.compress(src, target, False).close()
        
        
    def _ftp_connect(self):
        host = self.manager.configParser.get(self.sr_plugins['FTP'], 'host')
        userName = self.manager.configParser.get(self.sr_plugins['FTP'], 'user')
        userPass = self.manager.configParser.get(self.sr_plugins['FTP'], 'pass')
        port = self.manager.configParser.getint(self.sr_plugins['FTP'], 'port')
        workDir = self.manager.configParser.get(self.sr_plugins['FTP'], 'work_dir')
        
        self.ftp = self.manager.get_plugin(self.sr_plugins['FTP'])
        self.ftp.connect(host, userName, userPass, workDir, port)
        
        
    def _ftp_upload(self, filepath):
        self.ftp.upload(filepath)
        
        
    def _ftp_download(self, filename):
        # Implement here
        pass
        
    
    def initRepo(self, new=False):
        if new:
            self._create_dir_struct(True)
            self._gen_config_file('[backup]\n[plugins]\n')
        self._init_plugin_manager()
        
        
    def backup(self, stable):
        if not stable:
            dir_path = os.path.join(self.path, self.sr_directories['sr_dev'])
            depth = self.manager.configParser.getint('backup', 'depth')
            dir_list = os.listdir(dir_path)
            dir_list.sort()
            cnt = len(dir_list)
            if cnt >= depth:
                os.remove(os.path.join(dir_path, dir_list[0]))
            
        self._compress_src(stable)
        curDirPath = os.path.join(self.path, self.sr_directories['sr_cur'])
        shutil.rmtree(curDirPath)
        os.mkdir(curDirPath)
    
    
def main():
    ini_content = '''[backup]
depth = 5
[plugins]
sr_crawler = EclipseSrcCrawler
sr_compressor = PythonZip
sr_ftp = PythonFtp
[sr_ftp]
# only for upload use
host = public.sjtu.edu.cn
port = 21
user = mawenbao
pass = public
work_dir = upload/SourceRepoBackup'''

    sr = SourceRepository('/home/wilbur/Backup/SourceRepository')
    sr.initRepo()
    sr._copy_to_current('/home/wilbur/workspace')
    # sr.ftp_connect()
    # sr.ftp_upload(os.path.join(sr.path, sr.sr_directories['sr_sta'], '20110212175419backup.zip'))
    sr.backup(True)
    print('Done.')
        
if __name__ == '__main__':
    main()